import axios from "axios";
import type { ResponseType } from "axios";

type AxiosArg<T> = [string, ('get' | 'post' | 'put' | 'delete' | 'patch')?, T?, boolean?, ResponseType?, string?];

let CancelToken = axios.CancelToken;
let source = CancelToken.source();

/**
 * 刷新source状态
 */
const refreshAxios = (): void => {
  CancelToken = axios.CancelToken;
  source = CancelToken.source();
}

/**
 * 对axios进行再次封装
 * @param {string} args - 元组类型，请求体的各项参数，依次是请求地址、请求方法(可选默认为get)、发送的参数(可选)、是否有取消请求的可能、数据相应的类型(可选默认为json)、默认接口地址前缀(可选默认为/api)
 * @param callback - 请求成功时的回调函数，参数为请求得到的数据对象(可选)
 */
const $http = <T>(args: AxiosArg<T>, callback?: (...arg: any[]) => any): Promise<number> => {
  const [url, method = 'get', params, isCancelToken = false, responseType = 'json', baseURL = '/api'] = args;
  return new Promise<number>((resolve, reject) => {
    switch (method) {
      case 'get': case 'delete': {
        axios({
          url,
          method,
          params,
          baseURL,
          cancelToken: isCancelToken ? source.token : undefined,
        }).then(res => {
          const { data } = res;
          if (data.code === 1) { if (typeof callback !== 'undefined') callback(data?.data); }
          else console.log(data.msg);
          resolve(data.code);
        }).catch((error: any) => {
          console.log(error);
          reject();
        }); break;
      }
      case 'post': case 'put': case 'patch': {
        axios({
          url,
          method,
          data: params,
          responseType,
          baseURL,
          cancelToken: isCancelToken ? source.token : undefined,
        }).then(res => {
          const { data } = res;
          if (data.code === 1) { if (typeof callback !== 'undefined') callback(data.data); }
          else console.log(data.msg);
          resolve(data.code);
        }).catch((error: any) => {
          console.log(error);
          reject();
        }); break;
      }
    }
  })
}

export default $http
export { source, refreshAxios }